export let question_data = [
    {
        "id": 1,
        "question": "将json字符串 '{\"name\":\"zs\"}'转为json对象的语法？",
        "answer": "使用JSON.parse()方法，示例：JSON.parse('{\"name\":\"zs\"}')"
    },
    {
        "id": 2,
        "question": "this指向有哪些？ 改变this指向的方法有哪些？",
        "answer": "this指向情况：事件中指向事件源；对象方法中指向对象本身；全局函数、定时器、回调函数中指向window；箭头函数中指向所在作用域的this。改变this指向的方法：fn.call(obj, 实参1, 实参2...)、fn.apply(obj, [实参1, 实参2...])、var newfn = fn.bind(obj, 实参1, 实参2...)"
    },
    {
        "id": 3,
        "question": "let和var的区别？let和const的区别？",
        "answer": "let和var区别：var有预解析，let没有；let有块级作用域，var没有；var允许变量名重复，let不允许；let有暂时性死区，var没有。let和const区别：const声明即赋值，不能先声明后赋值，let可以；const定义的常量不可以被修改，let定义的变量可以修改"
    },
    {
        "id": 4,
        "question": "简述for..in循环和for..of循环的区别？",
        "answer": "for..in循环遍历对象的可枚举属性（包括对象自身的和继承的），遍历数组时遍历的是下标；for..of循环遍历可迭代对象（如数组、Set、Map等），遍历数组时遍历的是元素，遍历Set集合时遍历的是元素，遍历Map集合时遍历的是键值对"
    },
    {
        "id": 5,
        "question": "简述字符串中和正则 相关的api，并简述含义和返回值？",
        "answer": "字符串中和正则相关的API：str.replace(正则, 替换值)，返回替换后的字符串；str.search(字符串或正则)，返回首次出现的下标，找不到返回-1；str.match(正则)，如果正则带有g标志，返回所有匹配的数组，否则返回包含匹配信息的数组"
    },
    {
        "id": 6,
        "question": "写一个正则，用于匹配任意一个或者多个数字？",
        "answer": "/\\d+/"
    },
    {
        "id": 7,
        "question": "什么是事件对象，写出鼠标事件对象的属性有哪些？区别是什么？",
        "answer": "事件对象是事件发生时，浏览器创建的一个对象，包含了与事件相关的信息。鼠标事件对象的属性：e.clientX/e.clientY，鼠标相对于浏览器窗口可视区域的坐标；e.pageX/e.pageY，鼠标相对于文档页面的坐标；e.offsetX/e.offsetY，鼠标相对于事件源元素内边距的坐标"
    },
    {
        "id": 8,
        "question": "写出键盘事件对象的属性有哪些？",
        "answer": "键盘事件对象的属性：e.key，按下的键的字符串表示；e.code，按下的键的代码；e.keyCode（已弃用，建议使用e.key或e.code），按键的数字代码；e.ctrlKey，是否按下Ctrl键；e.shiftKey，是否按下Shift键；e.altKey，是否按下Alt键；e.metaKey，是否按下Meta键（如Windows键、Command键）"
    },
    {
        "id": 9,
        "question": "什么是事件委托，事件委托的好处是什么？",
        "answer": "事件委托是指将事件监听器绑定到父元素上，利用事件冒泡原理，当子元素上的事件触发时，会冒泡到父元素上，由父元素的事件监听器处理。好处：减少事件监听器的数量，提高性能；动态添加的子元素也能自动拥有事件处理；代码更简洁，便于维护"
    },
    {
        "id": 10,
        "question": "写出鼠标事件类型，键盘事件类型，表单事件类型？",
        "answer": "鼠标事件类型：click、dblclick、contextmenu、mousedown、mouseup、mousemove、mouseover、mouseout、mouseenter、mouseleave。键盘事件类型：keydown、keypress、keyup。表单事件类型：submit、reset、change、input、focus、blur"
    },
    {
        "id": 11,
        "question": "事件绑定的方式有哪些？区别是什么？",
        "answer": "事件绑定方式：DOM0级事件绑定（如ele.onclick = function(){}）和DOM2级事件绑定（如ele.addEventListener('click', function(){}, false)）。区别：DOM0级事件绑定只能绑定一个事件处理函数，后面的会覆盖前面的；DOM2级事件绑定可以绑定多个事件处理函数，按绑定顺序依次执行；DOM2级事件绑定可以控制事件捕获或冒泡阶段触发；DOM2级事件绑定可以通过removeEventListener()方法移除事件监听器"
    },
    {
        "id": 12,
        "question": "DOM操作样式时，获取样式的语法有哪些,含义是？",
        "answer": "获取样式的语法：ele.style.属性，获取内联样式；window.getComputedStyle(元素).属性或window.getComputedStyle(元素)['属性']，获取元素的计算样式（包括外部样式表、内联样式等所有应用的样式）。ele.offsetWidth获取元素的实际宽度（width + border + padding）；ele.clientWidth获取元素的可视宽度（width + padding，不包括border）；ele.offsetLeft获取元素距离它具有定位的父元素的左偏移量，如果父元素无定位，相对于浏览器窗口；ele.offsetTop获取元素距离它具有定位的父元素的上偏移量，如果父元素无定位，相对于浏览器窗口"
    },
    {
        "id": 13,
        "question": "DOM操作属性时，操作属性的语法有哪些？",
        "answer": "操作固有属性：ele.属性名（如ele.id、ele.src、ele.checked、ele.disabled、ele.href等）。操作自定义属性：ele.setAttribute('属性名', '属性值')设置属性，ele.getAttribute('属性名')获取属性，ele.removeAttribute('属性名')移除属性。操作data-*属性：ele.dataset.属性名（如ele.dataset.id等价于ele.getAttribute('data-id')，ele.dataset.id = '1'等价于ele.setAttribute('data-id', '1')）"
    },
    {
        "id": 14,
        "question": "DOM的创建元素节点，尾部追加，插入，克隆，替换，的语法？",
        "answer": "创建元素节点：document.createElement('标签名')；尾部追加：父元素.appendChild(新元素)；插入到指定元素之前：父元素.insertBefore(新元素, 参考元素)；克隆元素：元素.cloneNode(是否深克隆)，true表示克隆元素及其所有子元素，false表示只克隆元素本身；替换元素：父元素.replaceChild(新元素, 被替换元素)"
    },
    {
        "id": 15,
        "question": "写出数组中能改变原数组的api有哪些？",
        "answer": "能改变原数组的API：push()、pop()、shift()、unshift()、splice()、sort()、reverse()、fill()、copyWithin()"
    },
    {
        "id": 16,
        "question": "什么样的函数可以改造成箭头函数，怎么改？",
        "answer": "可以改造成箭头函数的情况：不需要自己的this、arguments、super或new.target的函数；没有使用yield关键字的函数。改造方法：去掉function关键字，在参数列表和函数体之间加上=>；如果只有一个参数，可以省略参数括号；如果函数体只有一条语句且是返回语句，可以省略花括号和return关键字"
    },
    {
        "id": 17,
        "question": "基本数据类型和引用数据类型的区别？",
        "answer": "基本数据类型（如Number、String、Boolean、Null、Undefined、Symbol）的变量直接存储值，存储在栈内存中；引用数据类型（如Object、Array、Function等）的变量存储的是对象在堆内存中的地址值，存储在栈内存中。基本数据类型的值赋值给其他变量时，是值的复制，两个变量互不影响；引用数据类型的值赋值给其他变量时，是地址值的复制，两个变量指向同一个对象，一个变量修改对象属性会影响另一个变量"
    },
    {
        "id": 18,
        "question": "数组中不能改变原数组的API有哪些？简述其作用和返回值",
        "answer": "- arr.indexOf(item, start)：在数组中搜索元素值并返回其位置，未找到返回-1。- arr.lastIndexOf(item, start)：返回指定元素最后一次出现的位置，未找到返回-1。- arr.join('连接符')：将所有数组元素结合为一个字符串，返回用连接符分隔的字符串。- arr.concat(arr1,arr2,arr3)：通过合并现有数组创建新数组，返回拼接后的新数组。- arr.includes(element)：检测数组中是否包含目标元素，返回布尔值。- arr.slice(index1,index2)：用数组的某个片段切出新数组，返回切出的新数组"
    },
    {
        "id": 19,
        "question": "ES5新增的数组API有哪些？简述其作用和参数",
        "answer": "- arr.forEach(myFunction)：为每个数组元素调用一次函数，参数为myFunction(value, index, array)，无返回值。- arr.map(myFunction)：执行回调函数映射出一个新数组，参数为myFunction(value, index, array)，返回映射后的新数组。- arr.filter(myFunction)：创建包含通过测试的数组元素的新数组，参数为myFunction(value, index, array)，返回过滤后的数组。- arr.some(myFunction)：检查某些数组值是否通过测试，有一个满足则返回true，参数为myFunction(value, index, array)，返回布尔值。- arr.every(myFunction)：检查所有数组值是否通过测试，全部满足才返回true，参数为myFunction(value, index, array)，返回布尔值"
    },
    {
        "id": 20,
        "question": "ES6新增的数组API有哪些？简述其作用和参数",
        "answer": "- Array.from(arrayLike, mapFn, thisArg)：从可迭代或类数组对象创建新数组实例，参数为类数组/可迭代对象、可选的映射函数和this值，返回新数组。- arr.find(myFunction)：返回通过测试函数的第一个数组元素的值，参数为myFunction(value, index, array)，返回该元素值。- arr.findIndex(myFunction)：返回通过测试函数的第一个数组元素的索引，参数为myFunction(value, index, array)，未找到返回-1。- arr.reduce(myFunction,0)：在每个元素上运行函数生成单个值，参数为myFunction(total, value, index, array)和初始值，返回计算后的单个值"
    },
    {
        "id": 21,
        "question": "字符串的常用API有哪些？简述其作用和返回值",
        "answer": "- str.split('分隔符')：将字符串以分隔符分割，返回分割后的数组。- str.concat(str1)：拼接字符串，返回拼接后的新字符串。- str.slice(开始下标,结束下标)：截取字符串，包含开始下标元素，不包含结束下标元素，返回截取的字符串。- str.indexOf('abc')：查找子串首次出现的下标，未找到返回-1，返回下标或-1。- str.includes('字符/字符串')：判断字符串是否包含目标子串，返回布尔值。- str.trim()：去除字符串前后空格，返回去除空格后的字符串。- str.toLowerCase()：将字符串转小写，返回转换后的字符串。- str.toUpperCase()：将字符串转大写，返回转换后的字符串。- str.replace(旧字符,新字符)：替换首次出现的旧字符为新字符，返回替换后的字符串"
    },
    {
        "id": 22,
        "question": "Math数学对象的常用方法有哪些？简述其作用",
        "answer": "- Math.random()：获取[0-1)的随机数。- Math.max(12,34,45,2)：获取传入数字中的最大值。- Math.min(12,34,45,2)：获取传入数字中的最小值。- Math.pow(2,3)：求2的3次方。- Math.sqrt(n)：对n开根号。- Math.round(5.4)：四舍五入。- Math.abs(-8)：取绝对值。- Math.ceil(8.3)：向上取整。- Math.floor(8.3)：向下取整"
    },
    {
        "id": 23,
        "question": "如何创建Date日期对象？日期对象有哪些常用API？",
        "answer": "创建方式：var date = new Date()创建当前日期对象；var date = new Date(\"2024/09/09 10:00:00\")创建特定时间对象。常用API：date.toLocaleString()将日期处理为字符串；date.getFullYear()获取年；date.getMonth()获取月(0-11)；date.getDate()获取日；date.getHours()获取时；date.getMinutes()获取分；date.getSeconds()获取秒；date.getMillSeconds()获取毫秒；date.getDay()获取星期(0-6，0为周日)"
    },
    {
        "id": 24,
        "question": "BOM中window对象的常用方法有哪些？简述其作用",
        "answer": "- window.alert()：浏览器弹框，无返回值。- window.prompt(\"提示输入的内容\")：浏览器输入框，返回用户输入的字符串。- window.confirm(\"提示确认信息\")：浏览器确认框，点击确定返回true，取消返回false。- window.setInterval(function(){},xxx)：间歇性定时，每隔xxx毫秒执行一次函数，返回定时器名称。- window.clearInterval(定时器名称)：清除指定定时器。- window.setTimeout(function(),xxx)：一次性定时器，xxx毫秒后执行一次函数，返回定时器标志。- window.clearTimeout(定时器名称)：清除一次性定时器"
    },
    {
        "id": 25,
        "question": "BOM中window的常用事件有哪些？简述其触发时机",
        "answer": "- window.onresize：浏览器窗口大小改变时触发。- window.onload：页面上所有内容（dom元素，视频，音频，图片）加载完毕时触发。- window.onscroll：滚动条滚动时触发。- window.onclick：点击窗口时触发"
    },
    {
        "id": 26,
        "question": "获取DOM元素的方法有哪些？简述其返回值",
        "answer": "非常规元素：document.body获取body元素；document.documentElement获取html元素。常规元素：document.getElementById(\"id名字\")获取唯一一个元素；document.getElementsByClassName(\"类名\")、document.getElementsByTagName(\"标签名\")、document.getElementsByName(\"表单的name值\")获取一组伪数组形式的元素；document.querySelector(\"选择器\")获取多个元素中的第一个；document.querySelectorAll(\"选择器\")获取所有选中的元素，返回伪数组"
    },
    {
        "id": 27,
        "question": "节点相关的获取方法有哪些？分别获取什么节点",
        "answer": "- document.body.firstElementChild：获取body的第一个元素节点。- oDiv.firstChild：获取节点的第一个节点。- oDiv.firstElementChild：获取节点的第一个元素节点。- oDiv.nextSibling：获取节点的下一个兄弟节点。- oDiv.previousSibling：获取节点的上一个兄弟节点。- oDiv.parentNode：获取节点的父节点。- oDiv.childNodes：获取节点的所有子节点"
    },
    {
        "id": 28,
        "question": "事件传播的三个阶段是什么？DOM0级和DOM2级事件绑定对事件传播的支持有何不同",
        "answer": "事件传播三阶段：1.事件捕获阶段；2.目标阶段（具体点击的元素，可通过evt.target获取）；3.事件冒泡阶段。DOM0级只支持事件冒泡（由内而外）；DOM2级既支持事件冒泡，也支持事件捕获（由外到内），通过addEventListener的第三个参数控制，true为捕获，false为冒泡（默认）"
    },
    {
        "id": 29,
        "question": "如何阻止事件冒泡和默认行为？",
        "answer": "阻止事件冒泡：使用e.stopPropagation()，写在具体点击的元素的事件处理函数中。阻止默认行为：e.preventDefault()支持DOM0和DOM2级，写在事件处理函数底部；return false支持DOM0级，写在事件处理函数底部"
    },
    {
        "id": 30,
        "question": "正则表达式的元字符、边界符、限定符分别有哪些？简述其含义",
        "answer": "元字符：\\d表示一位数字；\\D表示一位非数字；\\w表示一位数字、字母或下划线；\\W表示非数字、字母或下划线；\\s匹配空白字符；\\S非空白；.表示任意字符（非换行）；\\.匹配.；\\b表示单词边界；\\B表示非单词边界。边界符：^表示以...开始；$表示以...结束。限定符：*匹配0次或多次；+匹配1次或多次；?匹配0次或1次；{n}匹配正好n次；{n,m}匹配n-m次；{n,}匹配n次以上"
    },
    {
        "id": 31,
        "question": "正则表达式的定义方式有哪些？正则表达式的test方法的作用、参数和返回值是什么？",
        "answer": "正则表达式定义方式：字面量（var reg = /规则/[修饰符]）和构造函数（var reg = new RegExp('规则'[,修饰符])）。test方法：作用是检测字符串是否满足正则规则；参数为一个字符串；返回值为布尔值，满足返回true，不满足返回false"
    },
    {
        "id": 32,
        "question": "Set和Map的常用属性和方法有哪些？",
        "answer": "Set：属性size（元素数量）；方法add（添加元素）、delete（删除元素）、has（检测是否包含元素）、clear（清空所有元素）。Map：属性size（键值对数量）；方法set（添加键值对）、get（获取键对应的值）、delete（删除键值对）、clear（清空所有键值对）"
    },
    {
        "id": 33,
        "question": "展开运算符和合并运算符的作用是什么？如何使用？",
        "answer": "展开运算符（...）：展开数组（如console.log(...arr)将数组元素展开为独立值；let arr1 = [...arr, 12, 34]合并数组）；展开对象（let obj1 = {...obj, grade: 3}复制并扩展对象）；将伪数组转为数组（[...伪数组]）。合并运算符（...）：在函数参数中接受多个实参并合并为数组，如function fn(...args){console.log(args)}，调用fn(1,4,5)时args为[1,4,5]"
    },
    {
        "id": 34,
        "question": "数组和对象解构赋值的语法和作用是什么？",
        "answer": "数组解构：语法let [a, b, c] = [12, 34, 56]，作用是从数组中提取值，按照对应位置赋值给变量，可用于交换变量（[x, y] = [y, x]）、位取值（let [, x1, , y1] = arr）。对象解构：语法let { name } = obj 或 let { name: n, age: ag } = obj，作用是从对象中提取属性值，可指定变量名接收，简化对象属性的获取"
    },
    {
        "id": 35,
        "question": "数组去重的方法有哪些？请简述其中一种基于Set的方法",
        "answer": "数组去重方法包括使用Set、filter结合indexOf等。基于Set的方法：利用Set中元素唯一的特性，先将数组转为Set（let set1 = new Set(arr)），再通过展开运算符转回数组（[...set1]），示例：let arr = [12, 45, 34, 12, 46, 12]，去重后为[...new Set(arr)]"
    },
    {
        "id": 36,
        "question": "如何遍历对象？Object.keys和Object.values方法的作用和返回值是什么？",
        "answer": "遍历对象的方法包括for...in循环、使用Object.keys和Object.values等。Object.keys(obj)：作用是获取对象自身的所有可枚举属性名；返回值为包含属性名的数组。Object.values(obj)：作用是获取对象自身的所有可枚举属性值；返回值为包含属性值的数组"
    },
    {
        "id": 37,
        "question": "数组的flat方法的作用、参数和返回值是什么？",
        "answer": "作用：拍平（扁平化）数组，将多维数组拍平为一维数组。参数：数组维度（n），如果不确定嵌套层数，可传入Infinity参数。返回值：拍平后的数组"
    },
    {
        "id": 38,
        "question": "字符串的split方法的作用、参数和返回值是什么？如何将分割后的数组元素转为数值类型？",
        "answer": "作用：将字符串以分隔符位置分割成数组，分割后的数组元素类型都是字符串。参数：分隔符。返回值：分割后的数组。将元素转为数值类型：可借助map(Number)，如str.split(',').map(Number)"
    },
    {
        "id": 39,
        "question": "获取页面滚动相关信息的属性和方法有哪些？如何实现页面平滑滚动到顶部？",
        "answer": "获取滚动信息：document.documentElement.scrollTop（页面卷出去的高度）、document.documentElement.scrollLeft（页面卷出去的left值）。平滑滚动到顶部：window.scrollTo({ top: 0, behavior: 'smooth' })"
    },
    {
        "id": 40,
        "question": "获取视口宽度和高度的属性有哪些？简述其区别",
        "answer": "window.innerWidth和window.innerHeight：获取视口的宽度和高度，包含滚动条。document.documentElement.clientWidth和document.documentElement.clientHeight：获取视口的宽度和高度，不包含滚动条。document.body.clientWidth和document.body.clientHeight：获取body元素的宽度和高度，受body样式影响"
    },
    {
        "id": 41,
        "question": "location 对象的常用属性和方法有哪些？分别有什么作用？",
        "answer": "- location.href：获取或设置浏览器的 URL 地址，赋值新地址可实现页面跳转。- location.reload ()：重新加载当前页面。- location.search：获取 URL 中的查询字符串（以？开头的部分）。- location.assign (url)：加载新的 URL 并在历史记录中添加条目。- location.replace (url)：加载新的 URL 但不在历史记录中添加条目，无法通过后退按钮返回原页面"
    },
    {
        "id": 42,
        "question": "history 对象的常用方法有哪些？作用是什么？",
        "answer": "- history.go (1) 或 history.forward ()：向前跳转一个历史记录。- history.go (-1) 或 history.back ()：向后跳转一个历史记录。- history.go (0)：刷新当前页面。- history.go (n)：跳转 n 个历史记录（n 为正数向前，负数向后）。- history.length：返回当前窗口历史记录的数量"
    },
    {
        "id": 43,
        "question": "screen 对象的常用属性有哪些？作用是什么？",
        "answer": "- screen.width：获取屏幕的宽度。- screen.height：获取屏幕的高度。- screen.availWidth：获取屏幕可用宽度（排除任务栏等区域）。- screen.availHeight：获取屏幕可用高度（排除任务栏等区域）"
    },
    {
        "id": 44,
        "question": "节点的类型有哪些？分别对应什么数字常量？",
        "answer": "- 元素节点：对应数字 1。- 属性节点：对应数字 2（使用较少）。- 文本节点：对应数字 3。- 注释节点：对应数字 8。- 文档节点：对应数字 9"
    },
    {
        "id": 45,
        "question": "操作 DOM 元素内容的方法有哪些？分别适用于什么场景？",
        "answer": "- 非表单元素：使用 innerHTML 和 innerText。innerHTML 可识别 HTML 标签，innerText 仅获取纯文本；两者均可读写，设置时分别解析 HTML 或纯文本。- 表单元素：使用 value 属性，用于获取或设置输入框、文本域等表单元素的内容"
    },
    {
        "id": 46,
        "question": "事件处理函数中如何区分事件源和绑定事件的元素？",
        "answer": "在事件处理函数中，e.target 表示触发事件的具体元素（事件源），this 或 e.currentTarget 表示绑定事件的元素。例如点击子元素时，e.target 指向子元素，this 指向绑定事件的父元素（若事件绑定在父元素上）"
    },
    {
        "id": 47,
        "question": "什么是伪数组？伪数组有哪些特点？如何将伪数组转为真数组？",
        "answer": "伪数组是类似数组的对象，具有 length 属性和索引元素，但不具备数组的方法（如 push、map 等）。特点：有 length 属性、可通过索引访问元素、不继承 Array 原型方法。转换方法：使用 Array.from (伪数组) 或展开运算符 [... 伪数组]"
    },
    {
        "id": 48,
        "question": "正则表达式中的特殊符 []、()、[^] 分别有什么作用？",
        "answer": "- []：匹配括号内的任意一个字符，如 [abc] 匹配 a、b 或 c；可指定范围，如 [a-z] 匹配任意小写字母。- ()：将括号内的内容视为一个整体，如 (abc){2} 表示 “abc” 整体重复 2 次。- [^]：匹配除括号内字符外的任意字符，如 [^0-9] 匹配非数字字符"
    },
    {
        "id": 49,
        "question": "字符串的 slice、substring、substr 方法有什么区别？",
        "answer": "- slice (start, end)：start 为起始索引，end 为结束索引（不包含），支持负数索引（从末尾开始计算）。- substring (start, end)：与 slice 类似，但不支持负数索引，若 start > end 会自动交换两者。- substr (start, length)：start 为起始索引，length 为截取长度，支持负数 start（从末尾开始计算）"
    },
    {
        "id": 50,
        "question": "数组 reduce 和 reduceRight 方法的区别是什么？各适用于什么场景？",
        "answer": "两者语法相同，区别在于遍历方向：reduce 从左到右遍历数组，reduceRight 从右到左遍历。适用场景：reduce 适用于求和、扁平化数组等从左到右的累积操作；reduceRight 适用于函数组合、反转操作等从右到左的计算"
    },
    {
        "id": 51,
        "question": "什么是包装类型？字符串的包装类型如何创建？",
        "answer": "包装类型是为基本数据类型提供对象接口的特殊对象，如 String、Number、Boolean。字符串包装类型通过 new 关键字创建：var str = new String ('abc')，此时 str 为对象类型，可调用字符串方法（如 str.length、str.slice ()），但使用 typeof 检测为 'object'"
    },
    {
        "id": 52,
        "question": "键盘事件中 keydown、keypress、keyup 的触发顺序是什么？keypress 有什么限制？",
        "answer": "触发顺序：keydown → keypress → keyup。keypress 的限制：不支持功能键（如 Ctrl、Shift、Alt 等），仅在按下可打印字符时触发；无法识别某些特殊键（如 Backspace、Delete）的按下事件"
    },
    {
        "id": 53,
        "question": "mouseover 和 mouseenter、mouseout 和 mouseleave 的区别是什么？",
        "answer": "- mouseover 和 mouseout：会在子元素间切换时触发冒泡，即从父元素移入子元素时，父元素触发 mouseout，子元素触发 mouseover。- mouseenter 和 mouseleave：不会触发冒泡，仅在进入 / 离开绑定事件的元素本身时触发，子元素间切换不影响父元素"
    },
    {
        "id": 54,
        "question": "如何检测一个变量是否为数组？",
        "answer": "方法 1：Array.isArray (arr)，返回布尔值（推荐，ES5 新增）。方法 2：arr instanceof Array，判断变量是否为 Array 的实例。方法 3：Object.prototype.toString.call (arr) === '[object Array]'，通过对象原型方法检测类型"
    },
    {
        "id": 55,
        "question": "JSON.stringify 和 JSON.parse 的作用是什么？使用时有什么注意事项？",
        "answer": "- JSON.stringify (obj)：将 JavaScript 对象转为 JSON 字符串。- JSON.parse (str)：将 JSON 字符串转为 JavaScript 对象。注意事项：JSON 字符串中属性名必须用双引号；不能序列化函数、Symbol、循环引用的对象；解析非 JSON 格式字符串会报错"
    },
    {
        "id": 56,
        "question": "什么是函数的参数默认值？如何设置函数参数的默认值？",
        "answer": "参数默认值是指函数调用时未传递参数或传递 undefined 时使用的默认值。设置方法：在函数定义时为参数赋值，如 function fn (name = ' 默认名 '){}，调用 fn () 时 name 会使用默认值"
    },
    {
        "id": 57,
        "question": "数组的 splice 方法有哪些用法？分别举例说明",
        "answer": "- 删除元素：arr.splice (index, count)，如 arr.splice (1, 2) 从索引 1 开始删除 2 个元素。- 添加元素：arr.splice (index, 0, item1, item2)，如 arr.splice (2, 0, 'a', 'b') 从索引 2 开始插入元素。- 替换元素：arr.splice (index, count, item1)，如 arr.splice (1, 1, 'new') 替换索引 1 的元素为 'new'"
    },
    {
        "id": 58,
        "question": "如何实现数组的深拷贝？",
        "answer": "简易方法：使用 JSON.parse (JSON.stringify (arr))，通过先转为 JSON 字符串再解析的方式深拷贝数组（注意：无法拷贝函数、Symbol 等类型）。复杂方法：递归遍历数组，对每个元素判断是否为引用类型，若为数组则递归拷贝，否则直接赋值"
    },
    {
        "id": 59,
        "question": "正则表达式的修饰符 g、i、m 分别有什么作用？",
        "answer": "- g（全局匹配）：匹配所有符合条件的结果，而非仅第一个。- i（忽略大小写）：匹配时不区分大小写，如 /a/i 匹配 A 和 a。- m（多行匹配）：使 ^ 和 $ 匹配每行的开头和结尾，而非整个字符串的开头和结尾"
    },
    {
        "id": 60,
        "question": "window.scrollTo () 方法的参数有哪些？如何实现滚动到指定元素位置？",
        "answer": "scrollTo () 参数：可传入 x 和 y 坐标（如 window.scrollTo (0, 500)），或配置对象 { top, left, behavior }（behavior 为'smooth' 时实现平滑滚动）。滚动到指定元素：先获取元素的 offsetTop，再调用 window.scrollTo ({ top: 元素.offsetTop, behavior: 'smooth' })"
    },
    {
        "id": 61,
        "question": "什么是事件冒泡？如何利用事件冒泡实现事件委托？",
        "answer": "事件冒泡是指事件从触发元素（事件源）向上传播到父级、祖先级元素的过程。利用事件冒泡实现事件委托的原理：将事件绑定在父元素上，当子元素触发事件时，事件会冒泡到父元素，通过父元素的事件处理函数处理子元素的事件，可通过 e.target 判断具体触发事件的子元素"
    },
    {
        "id": 62,
        "question": "数组的 sort 方法默认排序规则是什么？如何实现数字的升序和降序排序？",
        "answer": "sort 方法默认按照字符串 Unicode 编码顺序排序，对于数字会按字符串处理（如 '25' > '100'）。实现数字升序：arr.sort (function (a, b){return a - b})；实现数字降序：arr.sort (function (a, b){return b - a})"
    },
    {
        "id": 63,
        "question": "字符串的 charAt 和 charCodeAt 方法有什么区别？",
        "answer": "- charAt (下标)：返回指定下标对应的字符，如 'abc'.charAt (1) 返回 'b'。- charCodeAt (下标)：返回指定下标对应字符的 ASCII 码值，如 'abc'.charCodeAt (1) 返回 98（'b' 的 ASCII 码）"
    },
    {
        "id": 64,
        "question": "什么是暂时性死区？它与 let 和 var 的使用有什么关系？",
        "answer": "暂时性死区是指在 let/const 声明变量之前，该变量无法被访问的区域。let/const 声明的变量存在暂时性死区，在声明前使用会报错；var 声明的变量因存在变量提升，在声明前使用不会报错（值为 undefined）"
    },
    {
        "id": 65,
        "question": "如何判断一个对象是否包含某个属性？",
        "answer": "- 使用 in 运算符：' 属性名 ' in 对象，返回布尔值（包括继承的属性）。- 使用 hasOwnProperty 方法：对象.hasOwnProperty (' 属性名 ')，返回布尔值（仅判断自身属性，不包括继承的）"
    },
    {
        "id": 66,
        "question": "数组的 every 和 some 方法有什么区别？",
        "answer": "- every：检测数组所有元素是否都满足条件，全部满足返回 true，只要有一个不满足就返回 false。- some：检测数组是否有至少一个元素满足条件，只要有一个满足就返回 true，全部不满足返回 false"
    },
    {
        "id": 67,
        "question": "什么是函数柯里化？简单举例说明",
        "answer": "函数柯里化是指将接受多个参数的函数转换为一系列接受单个参数的函数的过程。例如：function add (a) { return function (b) { return a + b; }}，调用时 add (1)(2) 返回 3，通过分步传递参数实现计算"
    },
    {
        "id": 68,
        "question": "正则表达式中如何匹配任意一个中文字符？",
        "answer": "使用 [\u4e00-\u9fa5]，其中 \u4e00 是 Unicode 中中文的起始编码，\u9fa5 是结束编码，该表达式可匹配任意一个中文字符"
    },
    {
        "id": 69,
        "question": "Date 对象的 getMonth 和 getDay 方法返回值有什么特殊之处？",
        "answer": "- getMonth ()：返回月份，范围是 0-11（0 代表 1 月，11 代表 12 月），需加 1 才是实际月份。- getDay ()：返回星期，范围是 0-6（0 代表星期日，1-6 分别代表星期一至星期六）"
    },
    {
        "id": 70,
        "question": "什么是闭包？闭包有什么作用？",
        "answer": "闭包是指函数嵌套中，内部函数引用外部函数的变量，且内部函数被外部访问，导致外部函数的变量不会被销毁的现象。作用：延长变量的生命周期、实现私有变量（避免全局污染）"
    },
    {
        "id": 71,
        "question": "数组的 map 和 forEach 方法有什么区别？",
        "answer": "- map：返回一个新数组，新数组元素是原数组元素经过回调函数处理后的结果，不改变原数组。- forEach：无返回值，仅用于遍历数组，对原数组无影响（若修改元素为引用类型的属性则会影响原数组）"
    },
    {
        "id": 72,
        "question": "如何获取当前时间的时间戳？",
        "answer": "获取时间戳的方法：new Date ().getTime ()；Date.now ()（ES5 新增，更简洁）；+new Date ()（通过隐式类型转换获取）"
    },
    {
        "id": 73,
        "question": "正则表达式中修饰符 g 和 i 的作用是什么？",
        "answer": "- g（全局匹配）：匹配所有符合条件的结果，而非仅第一个，如 'aaa'.replace (/a/g, 'b') 返回 'bbb'。- i（忽略大小写）：匹配时不区分大小写，如 /a/i 匹配 'A' 和 'a'，'AbC'.match (/abc/i) 返回匹配结果"
    },
    {
        "id": 74,
        "question": "什么是函数的返回值？没有显式 return 的函数返回什么？",
        "answer": "函数的返回值是函数执行完成后通过 return 语句返回的结果。没有显式 return 的函数，默认返回 undefined"
    },
    {
        "id": 75,
        "question": "数组的 filter 方法和 find 方法有什么区别？",
        "answer": "- filter：返回所有满足条件的元素组成的新数组，可能包含多个元素。- find：返回第一个满足条件的元素，只返回一个元素（若没有则返回 undefined）"
    },
    {
        "id": 76,
        "question": "如何给元素添加和移除类名？",
        "answer": "添加类名：元素.classList.add (' 类名 ')；移除类名：元素.classList.remove (' 类名 ')；切换类名（存在则移除，不存在则添加）：元素.classList.toggle (' 类名 ')"
    },
    {
        "id": 77,
        "question": "什么是原型链？它在 JavaScript 中起到什么作用？",
        "answer": "原型链是由对象的__proto__属性串联起来的链式结构，每个对象都有原型，原型也是对象，形成链式关联。作用：实现对象的属性和方法继承，当访问对象的属性 / 方法时，若自身没有，会沿着原型链向上查找"
    },
    {
        "id": 78,
        "question": "字符串的 trim 方法有什么作用？它能去除哪些位置的空格？",
        "answer": "trim 方法用于去除字符串前后的空格，返回去除空格后的新字符串。只能去除字符串开头和结尾的空格，无法去除中间的空格"
    },
    {
        "id": 79,
        "question": "如何实现两个数组的合并？",
        "answer": "- 使用 concat 方法：arr1.concat (arr2)，返回合并后的新数组（不改变原数组）。- 使用展开运算符：[...arr1, ...arr2]，返回合并后的新数组（不改变原数组）。- 使用 push 结合展开运算符：arr1.push (...arr2)，将 arr2 元素添加到 arr1 末尾（改变原数组）"
    },
    {
        "id": 80,
        "question": "什么是立即执行函数？它的作用是什么？",
        "answer": "立即执行函数是定义后立即执行的函数，语法为 (function (){})() 或 (()=>{})()。作用：创建独立的作用域，避免变量污染全局作用域，常用于模块化代码或初始化操作"
    },
    {
        "id": 81,
        "question": "什么是函数节流？如何实现简单的函数节流？",
        "answer": "函数节流是指规定一个时间间隔，在该时间间隔内，函数只能执行一次，超过间隔后才会再次执行。实现方法：使用定时器，记录上一次执行时间，每次触发时判断当前时间与上一次执行时间的差是否大于间隔时间，若大于则执行函数并更新上一次执行时间。示例：\nfunction throttle (fn, delay) {\n let lastTime = 0;\n return function () {\n const now = Date.now ();\n if (now - lastTime >= delay) {\n fn.apply (this, arguments);\n lastTime = now;\n }\n }\n}"
    },
    {
        "id": 82,
        "question": "什么是函数防抖？如何实现简单的函数防抖？",
        "answer": "函数防抖是指当事件触发后，延迟 n 秒后再执行函数，如果在 n 秒内又触发了事件，则重新计算延迟时间。实现方法：使用定时器，每次触发事件时清除之前的定时器，重新设置新的定时器。示例：\nfunction debounce (fn, delay) {\n let timer = null;\n return function () {\n clearTimeout (timer);\n timer = setTimeout (() => {\n fn.apply (this, arguments);\n }, delay);\n }\n}"
    },
    {
        "id": 83,
        "question": "数组的 find 和 filter 方法在性能上有什么差异？",
        "answer": "find 方法在找到第一个满足条件的元素后就会停止遍历，性能较好，适合只需要获取第一个符合条件元素的场景；filter 方法会遍历整个数组，找出所有满足条件的元素，性能相对较低，适合需要获取所有符合条件元素的场景"
    },
    {
        "id": 84,
        "question": "如何判断两个对象是否相等？",
        "answer": "对于基本数据类型的属性组成的对象，可通过 JSON.stringify (obj1) === JSON.stringify (obj2) 判断（注意：属性顺序不同会返回 false）；对于复杂对象，需递归遍历对象的每个属性，判断属性值是否相等（包括引用类型属性需进一步递归判断）"
    },
    {
        "id": 85,
        "question": "什么是原型继承？它有什么特点？",
        "answer": "原型继承是 JavaScript 中通过原型链实现的继承方式，子类的原型指向父类的实例。特点：子类可以继承父类的属性和方法；父类原型上的属性和方法的改变会影响所有子类实例；无法实现多继承"
    },
    {
        "id": 86,
        "question": "字符串的 indexOf 和 lastIndexOf 方法有什么区别？",
        "answer": "- indexOf (item, start)：从 start 位置开始（默认从 0 开始），从左到右查找 item 首次出现的位置，返回索引，未找到返回 - 1。- lastIndexOf (item, start)：从 start 位置开始（默认从末尾开始），从右到左查找 item 最后一次出现的位置，返回索引，未找到返回 - 1"
    },
    {
        "id": 87,
        "question": "如何实现数组的扁平化？",
        "answer": "实现方法：使用数组的 flat 方法，arr.flat (Infinity) 可将任意深度的多维数组扁平化为一维数组；使用递归，遍历数组，若元素为数组则递归扁平化，否则添加到结果数组中"
    },
    {
        "id": 88,
        "question": "什么是构造函数？构造函数与普通函数有什么区别？",
        "answer": "构造函数是用于创建对象的函数，通常首字母大写。区别：构造函数使用 new 关键字调用，普通函数直接调用；构造函数内部的 this 指向新创建的对象，普通函数的 this 指向调用者（非严格模式下默认指向 window）；构造函数默认返回新创建的对象，普通函数默认返回 undefined"
    },
    {
        "id": 89,
        "question": "正则表达式中如何匹配任意一个英文字母（包括大小写）？",
        "answer": "使用 [a-zA-Z]，其中 a-z 匹配任意小写英文字母，A-Z 匹配任意大写英文字母，组合起来可匹配任意一个英文字母"
    },
    {
        "id": 90,
        "question": "什么是对象的浅拷贝和深拷贝？它们有什么区别？",
        "answer": "浅拷贝是指只复制对象的表层属性，若属性值为引用类型，则复制的是地址，修改新对象的该属性会影响原对象；深拷贝是指复制对象的所有层级属性，包括引用类型属性，新对象与原对象完全独立，修改新对象的属性不会影响原对象"
    },
    {
        "id": 91,
        "question": "数组的 concat 方法和扩展运算符在合并数组时有什么区别？",
        "answer": "两者都可用于合并数组且不改变原数组。concat 方法可接收多个参数（数组或值），如 arr1.concat (arr2, 'a')；扩展运算符通过 [...arr1, ...arr2, 'a'] 的形式合并，在处理多个数组或添加单个值时语法更简洁"
    },
    {
        "id": 92,
        "question": "如何获取元素的计算样式？计算样式与内联样式有什么区别？",
        "answer": "获取计算样式：使用 window.getComputedStyle (元素) 方法。区别：计算样式包含元素所有应用的样式（内联、内部、外部样式表），是只读的；内联样式仅指通过元素的 style 属性设置的样式，是可读写的"
    },
    {
        "id": 93,
        "question": "什么是变量提升？var 和 let 的变量提升有什么不同？",
        "answer": "变量提升是指变量声明被提升到作用域顶部的现象。var 的变量提升会将声明和初始化（默认 undefined）都提升，在声明前使用变量不会报错（值为 undefined）；let 的变量提升只提升声明，不提升初始化，在声明前使用变量会触发暂时性死区报错"
    },
    {
        "id": 94,
        "question": "字符串的 match 方法在正则带 g 修饰符和不带 g 修饰符时有什么区别？",
        "answer": "- 不带 g 修饰符：返回一个数组，第一个元素是匹配的完整字符串，后续元素是捕获组内容，包含 index 和 input 属性。- 带 g 修饰符：返回一个包含所有匹配结果的数组，不包含捕获组、index 和 input 属性"
    },
    {
        "id": 95,
        "question": "如何判断一个变量的类型？",
        "answer": "- 使用 typeof 运算符：可判断基本数据类型（除 null 外），返回 'number'、'string'、'boolean'、'undefined'、'function'、'object'（null 和引用类型均返回 'object'）。- 使用 Object.prototype.toString.call (变量)：可准确判断所有类型，返回 '[object 类型]'，如 [object Array]、[object Object]"
    },
    {
        "id": 96,
        "question": "数组的 push 和 unshift 方法有什么区别？",
        "answer": "- push ()：向数组末尾添加一个或多个元素，返回新数组的长度。- unshift ()：向数组开头添加一个或多个元素，返回新数组的长度"
    },
    {
        "id": 97,
        "question": "什么是事件捕获？它与事件冒泡有什么区别？",
        "answer": "事件捕获是事件传播的第一阶段，事件从最外层的祖先元素向目标元素传播（由外到内）。区别：事件捕获方向是由外到内，事件冒泡方向是由内到外；DOM0 级事件绑定不支持事件捕获，DOM2 级通过 addEventListener 的第三个参数（true）支持事件捕获"
    },
    {
        "id": 98,
        "question": "如何实现字符串的反转？",
        "answer": "实现方法：将字符串转为数组（split ('')），反转数组（reverse ()），再转回字符串（join ('')），如 'abc'.split ('').reverse ().join ('') 返回 'cba'"
    },
    {
        "id": 99,
        "question": "数组的 pop 和 shift 方法有什么区别？",
        "answer": "- pop ()：删除数组的最后一个元素，返回被删除的元素，改变原数组。- shift ()：删除数组的第一个元素，返回被删除的元素，改变原数组"
    },
    {
        "id": 100,
        "question": "什么是模块化？JavaScript 中实现模块化的方式有哪些？",
        "answer": "模块化是将代码拆分为独立、可复用的模块的方式。实现方式：CommonJS（Node.js 中使用，通过 require 和 module.exports）；ES6 模块（通过 import 和 export）；AMD（异步模块定义，如 RequireJS）；UMD（通用模块定义，兼容 CommonJS 和 AMD）"
    },
    {
        "id": 101,
        "question": "什么是类数组？类数组与数组有何异同？",
        "answer": "类数组是具有 length 属性和索引元素的对象，如函数的 arguments 对象、DOM 集合等。相同点：都可通过索引访问元素，都有 length 属性。不同点：类数组不具备数组的原型方法（如 push、map），数组是 Array 的实例，继承了 Array 的所有方法"
    },
    {
        "id": 102,
        "question": "正则表达式中如何匹配空白字符？包括哪些字符？",
        "answer": "使用 \s 匹配空白字符，包括空格、制表符（\t）、换行符（\n）、回车符（\r）等"
    },
    {
        "id": 103,
        "question": "如何实现对象的深拷贝？请写出简单示例",
        "answer": "深拷贝可通过递归实现，示例：\nfunction deepClone (obj) {\n if (obj === null || typeof obj !== 'object') return obj;\n let clone = Array.isArray (obj) ? [] : {};\n for (let key in obj) {\n if (obj.hasOwnProperty (key)) {\n clone [key] = deepClone (obj [key]);\n }\n }\n return clone;\n}"
    },
    {
        "id": 104,
        "question": "字符串的 replace 方法中，第二个参数可以是函数吗？有什么作用？",
        "answer": "可以。当第二个参数是函数时，该函数会在每次匹配时被调用，函数的返回值将作为替换文本。函数接收的参数包括匹配的字符串、捕获组内容、匹配索引、原字符串等，可根据这些参数动态生成替换内容"
    },
    {
        "id": 105,
        "question": "什么是函数式编程？它有哪些特点？",
        "answer": "函数式编程是一种编程范式，将函数作为一等公民，强调使用纯函数和不可变数据。特点：函数可作为参数和返回值；避免副作用（纯函数）；数据不可变；通过组合函数实现复杂逻辑"
    },
    {
        "id": 106,
        "question": "数组的 reduce 方法的初始值有什么作用？不提供初始值会怎样？",
        "answer": "初始值作为 reduce 回调函数的第一个参数（total）的初始值。不提供初始值时，total 会取数组的第一个元素，回调函数从数组的第二个元素开始执行；若数组为空且不提供初始值，会报错"
    },
    {
        "id": 107,
        "question": "如何获取元素的偏移量？包括哪些属性？",
        "answer": "通过 offsetLeft 和 offsetTop 获取元素的偏移量，offsetLeft 是元素距离具有定位的父元素的左偏移量，offsetTop 是元素距离具有定位的父元素的上偏移量；若父元素无定位，则相对于 body"
    },
    {
        "id": 108,
        "question": "正则表达式中贪婪匹配和非贪婪匹配有什么区别？如何设置非贪婪匹配？",
        "answer": " 贪婪匹配会尽可能匹配最长的符合条件的字符串，非贪婪匹配会尽可能匹配最短的符合条件的字符串。在限定符后加？可设置非贪婪匹配，如.?（非贪婪）与.（贪婪）"
    },
    {
        "id": 109,
        "question": "什么是原型对象？构造函数、原型对象和实例对象之间的关系是什么？",
        "answer": "原型对象是构造函数的 prototype 属性指向的对象，用于存放实例共享的属性和方法。关系：构造函数的 prototype 指向原型对象；原型对象的 constructor 指向构造函数；实例对象的__proto__指向原型对象"
    },
    {
        "id": 110,
        "question": "字符串的 slice 方法参数为负数时如何处理？",
        "answer": "slice 方法的参数为负数时，会从字符串末尾开始计算索引，如 str.slice (-3) 表示从倒数第 3 个字符开始到末尾，str.slice (-5, -2) 表示从倒数第 5 个字符开始到倒数第 2 个字符（不包含）"
    },
    {
        "id": 111,
        "question": "如何禁止鼠标右键菜单？",
        "answer": "通过阻止 contextmenu 事件的默认行为实现，示例：\ndocument.oncontextmenu = function (e) {\n e.preventDefault ();\n return false;\n}"
    },
    {
        "id": 112,
        "question": "数组的 shift 和 unshift 方法对性能有什么影响？",
        "answer": "shift（删除首元素）和 unshift（在首部添加元素）会导致数组中所有元素的索引重新排列，对于大型数组，会产生较高的性能开销，效率低于 pop（删除尾元素）和 push（在尾部添加元素）"
    },
    {
        "id": 113,
        "question": "正则表达式中如何匹配一个单词的边界？",
        "answer": "使用 \b 匹配单词边界，如 \bcat\b 可匹配独立的 “cat” 单词，不匹配 “category” 中的 “cat”"
    },
    {
        "id": 114,
        "question": "什么是事件流？事件流的三个阶段是什么？",
        "answer": "事件流是指事件从产生到被处理的完整过程。三个阶段：1. 事件捕获阶段（从祖先元素到目标元素）；2. 目标阶段（事件到达目标元素）；3. 事件冒泡阶段（从目标元素到祖先元素）"
    },
    {
        "id": 115,
        "question": "字符串的 localeCompare 方法有什么作用？",
        "answer": "localeCompare 方法用于比较两个字符串，返回一个数字：-1（当前字符串在参数字符串之前）、0（相等）、1（当前字符串在参数字符串之后），可用于字符串排序"
    },
    {
        "id": 116,
        "question": "如何判断一个数组是否为空？",
        "answer": "判断数组长度是否为 0，即 arr.length === 0；同时需确保变量是数组，可结合 Array.isArray (arr) && arr.length === 0 判断"
    },
    {
        "id": 117,
        "question": "正则表达式中如何匹配除换行符外的任意字符？",
        "answer": "使用.（点号）匹配除换行符（\n）外的任意字符"
    },
    {
        "id": 118,
        "question": "什么是高阶函数？请举例说明",
        "answer": "高阶函数是指接收函数作为参数或返回函数的函数。例如 Array.map ()（接收回调函数作为参数）、Function.prototype.bind ()（返回一个新函数）"
    },
    {
        "id": 119,
        "question": "数组的 includes 方法与 indexOf 方法有什么区别？",
        "answer": "- includes：返回布尔值，直接表示数组是否包含目标元素，可检测 NaN（[NaN].includes (NaN) 返回 true）。- indexOf：返回目标元素的索引，未找到返回 - 1，无法检测 NaN（[NaN].indexOf (NaN) 返回 - 1）"
    },
    {
        "id": 120,
        "question": "如何动态创建 script 标签并加载外部脚本？",
        "answer": "示例：\nlet script = document.createElement ('script');\nscript.src = ' 外部脚本路径.js';\nscript.onload = function () { console.log (' 脚本加载完成 '); };\ndocument.body.appendChild (script);"
    }
];